package com.example.myweb.Service.Auth.Impl;

import com.example.myweb.Domain.Entity.*;

import com.example.myweb.Dto.AuthorInfoDTO;
import com.example.myweb.Dto.CommentDTO;
import com.example.myweb.Dto.CreateCommentDTO;
import com.example.myweb.Exception.CustomException;
import com.example.myweb.Repository.JpaRepository.ArticleRepository;
import com.example.myweb.Repository.JpaRepository.CommentRepository;
import com.example.myweb.Repository.JpaRepository.DynamicRepository;
import com.example.myweb.Repository.JpaRepository.LikeRepository;
import com.example.myweb.Service.Auth.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentRepository commentRepository;
    @Autowired
    private DynamicRepository dynamicRepository;
    @Autowired
    private ArticleRepository articleRepository;
    @Autowired
    private LikeRepository likeRepository;
//    @Override
//    @Transactional
//    public Comment createComment(Comment.ContentType contentType, Long contentId, CreateCommentDTO request, User currentUser) {
//        // 1. 验证被评论的内容是否存在
//        validateContentExists(contentType, contentId);
//
//        // 2. 如果是二级回复，验证父评论是否存在且属于同一内容
//        if (request.getParentCommentId() != null) {
//            commentRepository.findById(request.getParentCommentId())
//                    .filter(parent -> parent.getContentId().equals(contentId) && parent.getContentType().equals(contentType))
//                    .orElseThrow(() -> new CustomException("要回复的评论不存在或不属于当前内容", HttpStatus.NOT_FOUND));
//        } else {
//            // 只有一级评论才增加内容的评论总数
//            incrementCommentCount(contentType, contentId);
//        }
//
//        // 3. 创建并保存评论实体
//        Comment newComment = new Comment();
//        newComment.setContentType(contentType);
//        newComment.setContentId(contentId);
//        newComment.setUser(currentUser);
//        newComment.setCommentText(request.getCommentText());
//        newComment.setParentCommentId(request.getParentCommentId());
//
//        return commentRepository.save(newComment);
//    }
//
//    @Override
//    @Transactional
//    public void deleteComment(Long commentId, User currentUser) {
//        Comment comment = commentRepository.findById(commentId)
//                .orElseThrow(() -> new CustomException("评论不存在", HttpStatus.NOT_FOUND));
//
//        // 权限校验：只有评论作者或内容作者可以删除 (简化为只有作者能删)
//        if (!comment.getUser().getUserId().equals(currentUser.getUserId())) {
//            throw new CustomException("无权删除该评论", HttpStatus.FORBIDDEN);
//        }
//
//        // 如果删除的是一级评论，需要将其内容的评论数-1
//        if (comment.getParentCommentId() == null) {
//            decrementCommentCount(comment.getContentType(), comment.getContentId());
//        }
//
//        // 删除评论 (如果数据库设置了级联删除，其下的回复也会被删除)
//        commentRepository.delete(comment);
//    }
//
//
//
//
//    @Override
//    @Transactional(readOnly = true)
//    public Page<CommentDTO> getComments(Comment.ContentType contentType, Long contentId, Pageable pageable) {
//        // 1. 分页查询所有一级评论
//        Page<Comment> topLevelCommentPage = commentRepository.findByContentTypeAndContentIdAndParentCommentIdIsNull(
//                contentType, contentId, pageable
//        );
//
//        // 2. 获取一级评论的ID列表
//        List<Long> topLevelCommentIds = topLevelCommentPage.getContent().stream()
//                .map(Comment::getCommentId)
//                .collect(Collectors.toList());
//
//        // 3. 一次性查询出所有相关的二级评论
//        List<Comment> replies = List.of(); // 默认为空列表
//        if (!topLevelCommentIds.isEmpty()) {
//            replies = commentRepository.findByContentTypeAndParentCommentIdIn(contentType, topLevelCommentIds);
//        }
//
//        // 4. 将二级评论按其父评论ID进行分组
//        Map<Long, List<Comment>> repliesMap = replies.stream()
//                .collect(Collectors.groupingBy(Comment::getParentCommentId));
//
//        // 5. 将 Page<Comment> 转换为 Page<CommentDTO>，并组装二级回复
//        return topLevelCommentPage.map(topLevelComment -> {
//            CommentDTO dto = convertToDto(topLevelComment);
//            // 从 Map 中获取当前一级评论对应的所有二级回复
//            List<Comment> childComments = repliesMap.getOrDefault(topLevelComment.getCommentId(), List.of());
//            // 将二级回复的实体列表转换为DTO列表并设置
//            List<CommentDTO> replyDTOs = childComments.stream()
//                    .map(this::convertToDto)
//                    .collect(Collectors.toList());
//            dto.setReplies(replyDTOs);
//            return dto;
//        });
//    }
@Override
@Transactional
public Comment createComment(Comment.ContentType contentType, Long contentId, CreateCommentDTO request, User currentUser) {
    // 1. 验证被评论的内容是否存在
    validateContentExists(contentType, contentId);

    // 2. 如果是二级回复，验证父评论是否存在且属于同一内容
    if (request.getParentCommentId() != null) {
        commentRepository.findById(request.getParentCommentId())
                .filter(parent -> parent.getContentId().equals(contentId) && parent.getContentType().equals(contentType))
                .orElseThrow(() -> new CustomException("要回复的评论不存在或不属于当前内容", HttpStatus.NOT_FOUND));
    } else {
        // 只有一级评论才增加内容的评论总数
        incrementCommentCount(contentType, contentId);
    }

    // 3. 创建并保存评论实体
    Comment newComment = new Comment();
    newComment.setContentType(contentType);
    newComment.setContentId(contentId);
    newComment.setUser(currentUser);
    newComment.setCommentText(request.getCommentText());
    newComment.setParentCommentId(request.getParentCommentId());

    return commentRepository.save(newComment);
}

    @Override
    @Transactional
    public void deleteComment(Long commentId, User currentUser) {
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new CustomException("评论不存在", HttpStatus.NOT_FOUND));

        // 权限校验：只有评论作者或内容作者可以删除 (简化为只有作者能删)
        if (!comment.getUser().getUserId().equals(currentUser.getUserId())) {
            throw new CustomException("无权删除该评论", HttpStatus.FORBIDDEN);
        }

        // 如果删除的是一级评论，需要将其内容的评论数-1
        if (comment.getParentCommentId() == null) {
            decrementCommentCount(comment.getContentType(), comment.getContentId());
        }

        // 删除评论 (如果数据库设置了级联删除，其下的回复也会被删除)
        commentRepository.delete(comment);
    }


    @Override
    @Transactional(readOnly = true)
    public Page<CommentDTO> getComments(Comment.ContentType contentType, Long contentId, Pageable pageable, User currentUser) {
        // 1. 分页查询一级评论
        Page<Comment> topLevelPage = commentRepository.findByContentTypeAndContentIdAndParentCommentIdIsNull(contentType, contentId, pageable);

        List<Comment> topLevelComments = topLevelPage.getContent();
        if (topLevelComments.isEmpty()) {
            return Page.empty(pageable);
        }

        // 2. 收集所有一级评论和可能存在的二级回复的ID，用于一次性查询点赞状态
        List<Long> allCommentIds = new ArrayList<>();
        List<Long> topLevelIds = topLevelComments.stream().map(Comment::getCommentId).collect(Collectors.toList());
        allCommentIds.addAll(topLevelIds);

        // 3. 一次性查询所有二级回复
        List<Comment> replies = commentRepository.findByParentCommentIdIn(topLevelIds);
        allCommentIds.addAll(replies.stream().map(Comment::getCommentId).collect(Collectors.toList()));

        // 4. 一次性查询当前用户对所有这些评论的点赞状态
        final Set<Long> likedCommentIds; // 声明为 final
//        if (currentUser != null && !allCommentIds.isEmpty()) {
//            // 如果用户已登录且有评论需要检查
//            likedCommentIds = likeRepository.findAllByUserAndTargetTypeAndTargetIdIn(currentUser, "COMMENT", allCommentIds)
//                    .stream()
//                    .map(Like::getTargetId)
//                    .collect(Collectors.toSet());
//        }
        if (currentUser != null && !allCommentIds.isEmpty()) {
            likedCommentIds = likeRepository.findAllByUserAndTargetTypeAndTargetIdIn(
                            currentUser,
                            Like.LikeTargetType.COMMENT, // <<< 将字符串 "COMMENT" 修改为枚举常量
                            allCommentIds
                    )
                    .stream()
                    .map(Like::getTargetId)
                    .collect(Collectors.toSet());
        }else {
            // 如果用户未登录或没有任何评论
            likedCommentIds = Collections.emptySet(); // 使用一个空的、不可变的Set
        }

        // 5. 组装数据 (这一部分我们可以使用上一轮优化后的代码)
        Map<Long, List<CommentDTO>> repliesMap = replies.stream()
                .collect(Collectors.groupingBy(
                        Comment::getParentCommentId,
                        Collectors.mapping(reply -> convertToDto(reply, likedCommentIds), Collectors.toList())
                ));

        return topLevelPage.map(comment -> {
            CommentDTO dto = convertToDto(comment, likedCommentIds);
            dto.setReplies(repliesMap.getOrDefault(comment.getCommentId(), Collections.emptyList()));
            return dto;
        });
    }

    // --- 辅助方法 ---
    private CommentDTO convertToDto(Comment comment, Set<Long> likedCommentIds) {
        CommentDTO dto = new CommentDTO();
        dto.setCommentId(comment.getCommentId());
        dto.setCommentText(comment.getCommentText());
        dto.setLikeCount(comment.getLikeCount());
        dto.setCommentTime(comment.getCommentTime());
        dto.setUser(new AuthorInfoDTO(comment.getUser().getUserId(), comment.getUser().getNickname(), comment.getUser().getAvatarUrl()));
        dto.setLiked(likedCommentIds.contains(comment.getCommentId()));
        return dto;
    }

    // --- 辅助方法重构 ---

    // 验证内容是否存在
    private void validateContentExists(Comment.ContentType contentType, Long contentId) {
        boolean exists = switch (contentType) {
            case DYNAMIC -> dynamicRepository.existsById(contentId);
            case ARTICLE -> articleRepository.existsById(contentId);
        };
        if (!exists) {
            throw new CustomException("要评论的内容不存在", HttpStatus.NOT_FOUND);
        }
    }
    private Long findParentId(List<Comment> replies, Long replyId) {
        return replies.stream()
                .filter(r -> r.getCommentId().equals(replyId))
                .findFirst()
                .map(Comment::getParentCommentId)
                .orElse(null);
    }

    // 增加评论数
    private void incrementCommentCount(Comment.ContentType contentType, Long contentId) {
        switch (contentType) {
            case DYNAMIC -> {
                Dynamic dynamic = dynamicRepository.findById(contentId).orElseThrow(); // 在validateContentExists后，这里不会报错
                dynamic.setCommentCount(dynamic.getCommentCount() + 1);
                dynamicRepository.save(dynamic);
            }
            case ARTICLE -> {
                Article article = articleRepository.findById(contentId).orElseThrow();
                article.setCommentCount(article.getCommentCount() + 1);
                articleRepository.save(article);
            }
        }
    }
    /**
     * 减少指定内容的评论总数。
     * @param contentType 内容类型 (ARTICLE 或 DYNAMIC)
     * @param contentId 内容ID
     */
    private void decrementCommentCount(Comment.ContentType contentType, Long contentId) {
        switch (contentType) {
            case ARTICLE -> articleRepository.findById(contentId).ifPresent(article -> {
                // 使用 Math.max 确保计数器不会变为负数
                article.setCommentCount(Math.max(0, article.getCommentCount() - 1));
                articleRepository.save(article);
            });
            case DYNAMIC -> dynamicRepository.findById(contentId).ifPresent(dynamic -> {
                dynamic.setCommentCount(Math.max(0, dynamic.getCommentCount() - 1));
                dynamicRepository.save(dynamic);
            });
        }
    }

    // convertToDto 方法保持不变
//    private CommentDTO convertToDto(Comment comment) {
//        CommentDTO dto = new CommentDTO();
//        dto.setCommentId(comment.getCommentId());
//        dto.setCommentText(comment.getCommentText());
//        dto.setLikeCount(comment.getLikeCount());
//        dto.setCommentTime(comment.getCommentTime());
//        dto.setUser(new AuthorInfoDTO(
//                comment.getUser().getUserId(),
//                comment.getUser().getNickname(),
//                comment.getUser().getAvatarUrl()
//        ));
//        // 注意：这里的 replies 是在 getComments 方法中被设置的
//        return dto;
//    }
}